<template>
  <up-form ref="formRef" :model="modelValue" :rules="rules">
    <up-row gutter="20rpx">
      <up-col v-for="item in items" :key="item.key" :span="item.span || 24">
        <up-form-item :label="item.label" :name="item.key">
          <!-- 当没穿插槽的时候，就默认，否则自定义 -->
          <slot :name="item.key">
            <component :is="getComponenst(item.type)" v-bind="getProps(item)" v-model="modelValue[item.key]">
            </component>
          </slot>
        </up-form-item>
      </up-col>
    </up-row>
  </up-form>
</template>
<script lang="ts" setup>
import {Input, InputNumber, Select} from 'uview-plus'
import {defineModel, defineProps, ref} from 'vue'

/**
 *   {
 *     key: 'age',
 *     label: '年龄',
 *     type: 'number',
 *     hidden: true,
 *     props: {  // 怎么将props去掉 ,通过getProps
 *       placeholder: 'age',
 *       options: [
 *        {
 *          label: '1',
 *          value: 1
 *        },
 *        {
 *          label: '2',
 *          value: 2
 *        }
 *      ]
 *     },
 *     onClick(){
 *        console.log('111')
 *     }
 *   }
 *
 *   当需要传自定义组件的时候，也就是type不是input,number,select的时候，
 *   可以在componentMap中进行定义，但是如果是只用一次的，那么就没必要在里面进行定义
 *   使用getComponents
 *   type: ()=>h('div',{},'自定义组件')
 *   type: HelloWorld
 *
 *   默认input
 *
 *   当hidden需要动态判断，例如name为张三的时候才需要进行隐藏，直接将传入的formItems 定义为computed即可
 */

const props = defineProps(['formItems', 'rules'])

const modelValue = defineModel()
const formRef = ref()

const componentMap = {
  input: Input,
  number: InputNumber,
  select: Select
}

const items = computed(() => {
  return props.formItems.filter(i => !i.hidden)
})

// 不需要当成props
const rootPorps = ['label', 'key', 'type']

function getProps(item) {
  if (item.props) return item.props
  return omit(item, rootPorps)
}

function getComponenst(type) {
  // type只要不是字符串
  if (type && typeof type !== 'string') {
    return type
  }

  return componentMap[type || 'input']
}

defineExpose({
  validate(...args) {
    return formRef.value.validate(...args)
  },
  resetFields(...args) {
    return formRef.value.resetFields(...args)
  }
})


// 怎么将这个组件改为函数式组件
// 新建FormBuilder.ts

/*import {h,ref} from 'vue'
// 导入该组件
import aForm from '@/components/a-form.vue'

export const useFormBuilder = (props)=>{
  const formRef = ref()
  const Component = (_,{slots})=>{
    return h(aForm,{
      ref:formRef,
      ...reactive(props) // 自动解包
    },slots)
  }

  return {
    formRef,
    Component
  }
}

// 使用
const {formRef,Component} = useFormBuilder({
  formItems:[
    {
      key:'name',
      label:'姓名'
    }
  ],
  rules:{
    name:[
      {
        required:true,
        message:'请输入姓名'
      }
    ]
  }
})

<Component></Component>*/
</script>

<style scoped lang="scss">

</style>